#pragma once
#include <string>
#include <map>
#include "SimulationParameters.h"
#include "ListNode.h"
#include "List.h"

enum CacheManagement { LRU, FIFO };

class Cache
{
protected:
	double _size;					// number of extents in the cache
	double _readSize;				// read extents capacity
	double _writeSize;				// write extents capacity
	
	List* _readList;
	List* _writeList;
	std::map<std::string, ListNode*>* _extents;
	
	//void bringNextExtents(ExtentIO* eio);
	int hasSpace(ExtentIO* eio);

	long _writeCount;
	long _totalWriteCount;
	long _ioCount;
	long _totalIOCount;
	double _availableTime;
	int _dirtyBitcounter;

	CacheManagement _policy;			// policy of the insert and remove from the cache (CacheManagement types)
	
	void initPolicy(CacheManagement policy);
	bool existsInCache(ExtentIO* eio);
public:
	Cache(long size, double readCacheSize, double writeCacheSize, CacheManagement policy);
	virtual ~Cache(void);
	bool exists(ExtentIO* eio);
	
	
	double getNextTime(void);
	void insert(ExtentIO* eio);
	
	void deleteFromWriteCache(std::string extentID);

	void increaseDirtyCounter();
	void decreaseDirtyCounter();
	int getDirtyCounter();

	int getWriteCount() const; 
	void resetWriteCount();
	void increaseWrites();

	int getIOCount() const; 
	void resetIOCount();
	void increaseIOs();
	
	int getTotalIOCount() const; 
	int getTotalWriteCount() const;
	double getWritePercentage();
	ExtentIO* getNextWrite();
	double getCachePercentage();

	//bool isPreviousInCache(ExtentIO* eio);

	ExtentIO* removeFromWrite(std::string extentID);
	void addToRead(ExtentIO*);

	std::string getIOID(ExtentIO* eio);
	virtual int getCacheAlignment() { return SimulationParameters::CacheAlignment; }
	virtual void removeLatestExtents (int count, bool isWrite);
};

